{- This file is part of funbot.
 -
 - Written in 2015 by fr33domlover <fr33domlover@riseup.net>.
 -
 - ♡ Copying is an act of love. Please copy, reuse and share.
 -
 - The author(s) have dedicated all copyright and related and neighboring
 - rights to this software to the public domain worldwide. This software is
 - distributed without any warranty.
 -
 - You should have received a copy of the CC0 Public Domain Dedication along
 - with this software. If not, see
 - <http://creativecommons.org/publicdomain/zero/1.0/>.
 -}

module FunBot.Settings.MkOption
    ( mkOptionF
    , mkOptionF'
    , mkOptionB
    , mkOptionP
    )
where

import Data.Settings.Option
import Data.Settings.Types
import Network.IRC.Fun.Bot.State (saveBotState)

import FunBot.Settings.Persist
import FunBot.Types
import FunBot.Util

-- | An option whose value is held by funbot's 'Settings' and saved into its
-- settings file.
mkOptionF :: OptionValue v
          => (Settings -> v)             -- ^ Get
          -> (v -> Settings -> Settings) -- ^ Set which never fails
          -> v                           -- ^ Default value for reset
          -> SettingsOption
mkOptionF get set defval = mkOptionS get set' reset cb
    where
    set' v s = Just $ set v s
    reset s = (Just defval, set defval s)
    cb = const saveBotSettings

-- | A variant of 'mkOptionF' which accepts a callback to run after the default
-- one.
mkOptionF' :: OptionValue v
           => (Settings -> v)             -- ^ Get
           -> (v -> Settings -> Settings) -- ^ Set which never fails
           -> v                           -- ^ Default value for reset
           -> (v -> BotSession ())        -- ^ Additional callback
           -> SettingsOption
mkOptionF' get set defval cbx = mkOptionS get set' reset cb
    where
    set' v s = Just $ set v s
    reset s = (Just defval, set defval s)
    cb v = saveBotSettings >> cbx v

-- | An option whose value is held by irc-fun-bot's 'BotState' and saved into
-- its state file.
mkOptionB :: OptionValue v
          => BotSession v         -- ^ Get
          -> (v -> BotSession ()) -- ^ Set which never fails
          -> v                    -- ^ Default value for reset
          -> SettingsOption
mkOptionB get set defval = mkOptionV get set' reset
    where
    setTo val = set val >> cb val
    set' val = setTo val >> return True
    reset = setTo defval
    cb = const saveBotState

-- | An option whose value is held in the SQL DB.
mkOptionP
    :: OptionValue v
    => BotSessionDB v         -- ^ Get
    -> (v -> BotSessionDB ()) -- ^ Set which never fails
    -> v                      -- ^ Default value for reset
    -> SettingsOption
mkOptionP get set defval = mkOptionV get' set' reset
    where
    get' = runDB get
    set' val = runDB $ set val >> return True
    reset = runDB $ set defval
